"""HTML cleaner for removing tags and extracting text"""

from typing import Dict, Any, Optional
from bs4 import BeautifulSoup
import html
import re
import logging

from .base_cleaner import BaseCleaner

logger = logging.getLogger(__name__)


class HTMLCleaner(BaseCleaner):
    """Cleaner for removing HTML tags and extracting clean text
    
    Preserves meaningful attributes like alt text and titles
    """
    
    def __init__(self, config: Optional[Dict[str, Any]] = None):
        """Initialize HTML cleaner
        
        Args:
            config: Configuration with options:
                - preserve_alt: Whether to preserve alt text (default: True)
                - preserve_title: Whether to preserve title attributes (default: True)
                - parser: BeautifulSoup parser to use (default: 'html.parser')
        """
        super().__init__(config)
        self.preserve_alt = self.config.get('preserve_alt', True)
        self.preserve_title = self.config.get('preserve_title', True)
        self.parser = self.config.get('parser', 'html.parser')
    
    def clean(self, data: Dict[str, Any]) -> Dict[str, Any]:
        """Clean HTML from the data
        
        Args:
            data: Input data dictionary
            
        Returns:
            Data with cleaned HTML fields
        """
        # Clean title if present
        if 'title' in data and data['title']:
            data['title'] = self._clean_html(data['title'])
        
        # Clean content if present
        if 'content' in data and data['content']:
            if isinstance(data['content'], str):
                data['content'] = self._clean_html(data['content'])
            elif isinstance(data['content'], dict):
                # Handle nested content structure
                for key, value in data['content'].items():
                    if isinstance(value, str):
                        data['content'][key] = self._clean_html(value)
        
        # Clean description if present
        if 'description' in data and data['description']:
            data['description'] = self._clean_html(data['description'])
        
        # Clean excerpt if present
        if 'excerpt' in data and data['excerpt']:
            data['excerpt'] = self._clean_html(data['excerpt'])
        
        return data
    
    def _clean_html(self, text: str) -> str:
        """Clean HTML from a text string
        
        Args:
            text: HTML text to clean
            
        Returns:
            Cleaned text without HTML tags
        """
        if not text:
            return text
        
        try:
            # Parse HTML
            soup = BeautifulSoup(text, self.parser)
            
            # Extract alt text from images if configured
            if self.preserve_alt:
                for img in soup.find_all('img'):
                    alt_text = img.get('alt', '')
                    if alt_text:
                        img.replace_with(f'[Image: {alt_text}]')
            
            # Extract title attributes if configured
            if self.preserve_title:
                for elem in soup.find_all(attrs={'title': True}):
                    title = elem.get('title', '')
                    if title and title not in elem.get_text():
                        elem.append(f' ({title})')
            
            # Extract text
            text = soup.get_text(separator=' ', strip=True)
            
            # Unescape HTML entities
            text = html.unescape(text)
            
            # Clean up whitespace
            text = self._normalize_whitespace(text)
            
            # Remove any remaining HTML-like patterns
            text = self._remove_html_patterns(text)
            
            return text
            
        except Exception as e:
            logger.error(f"Error cleaning HTML: {e}")
            # Return original text if cleaning fails
            return text
    
    def _normalize_whitespace(self, text: str) -> str:
        """Normalize whitespace in text
        
        Args:
            text: Text to normalize
            
        Returns:
            Text with normalized whitespace
        """
        # Replace multiple spaces with single space
        text = re.sub(r'\s+', ' ', text)
        
        # Remove leading/trailing whitespace
        text = text.strip()
        
        # Fix spacing around punctuation
        text = re.sub(r'\s+([,.!?;:])', r'\1', text)
        text = re.sub(r'([,.!?;:])\s*', r'\1 ', text)
        
        return text.strip()
    
    def _remove_html_patterns(self, text: str) -> str:
        """Remove any remaining HTML-like patterns
        
        Args:
            text: Text to clean
            
        Returns:
            Text without HTML patterns
        """
        # Remove any remaining tags
        text = re.sub(r'<[^>]+>', '', text)
        
        # Remove HTML comments
        text = re.sub(r'<!--.*?-->', '', text, flags=re.DOTALL)
        
        # Remove JavaScript/CSS blocks
        text = re.sub(r'<script.*?</script>', '', text, flags=re.DOTALL | re.IGNORECASE)
        text = re.sub(r'<style.*?</style>', '', text, flags=re.DOTALL | re.IGNORECASE)
        
        # Remove common HTML entities that might remain
        entities = {
            '&nbsp;': ' ',
            '&amp;': '&',
            '&lt;': '<',
            '&gt;': '>',
            '&quot;': '"',
            '&apos;': "'",
            '&#39;': "'",
            '&mdash;': '—',
            '&ndash;': '–',
            '&hellip;': '...',
            '&copy;': '©',
            '&reg;': '®',
            '&trade;': '™'
        }
        
        for entity, replacement in entities.items():
            text = text.replace(entity, replacement)
        
        return text